﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace CustomControls
{
    public partial class ChatOutputControl : Panel
    {
        List<ChatTextLine> Lines;

        public ChatOutputControl()
        {
            InitializeComponent();
            this.Lines = new List<ChatTextLine>();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            PointF curpos = new PointF(0, 0);

            e.Graphics.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);

            foreach (ChatTextLine l in Lines)
            {
                foreach (ChatTextBlock B in l)
                {
                    ChatTextBlock[] blocksToWrite = null;
                    if ((blocksToWrite = WordWrapOnWhiteSpace(B, curpos, e.Graphics)) == null)
                        blocksToWrite = WordWrapOnChars(B, curpos, e.Graphics);

                    SizeF Rlast = new SizeF();
                    foreach (ChatTextBlock b in blocksToWrite)
                    {
                        Rlast = e.Graphics.MeasureString(b.Text, b.BlockFont);
                        e.Graphics.DrawString(b.Text, b.BlockFont, new SolidBrush(b.BlockColor), curpos);

                        if (b != blocksToWrite[blocksToWrite.Length - 1])
                            curpos = new PointF(0, curpos.Y + Rlast.Height + 10);

                        else
                            curpos = new PointF(curpos.X + Rlast.Width, curpos.Y);
                    }
                }

                curpos = new PointF(0, curpos.Y + this.Font.Height + 1);
            }

        }

        private ChatTextBlock[] WordWrapOnChars(ChatTextBlock T, PointF Curpos, Graphics G)
        {
            List<ChatTextBlock> Ret = new List<ChatTextBlock>();

            if (G.MeasureString(T.Text, T.BlockFont).Width < (this.Width - Curpos.X))
                return new ChatTextBlock[] { T };

            for (int i = T.Text.Length - 1; i > 0; i--)
            {
                if (G.MeasureString(T.Text.Substring(0, i), T.BlockFont).Width < (this.Width - Curpos.X))
                {
                    Ret.Add(new ChatTextBlock(T.BlockFont, T.Text.Substring(0, i), T.BlockColor));
                    Ret.AddRange(this.WordWrapOnChars(new ChatTextBlock(T.BlockFont, T.Text.Substring(i - 1, T.Text.Length - i), T.BlockColor), new PointF(0, G.MeasureString(T.Text, T.BlockFont).Height + Curpos.Y), G));
                    return Ret.ToArray();
                }
            }

            return null;
        }

        private ChatTextBlock[] WordWrapOnWhiteSpace(ChatTextBlock T, PointF curpos, Graphics G)
        {
            List<ChatTextBlock> Ret = new List<ChatTextBlock>();

            if (G.MeasureString(T.Text, T.BlockFont).Width >= (this.Width - curpos.X))
            {
                string[] temp = T.Text.Split(' ');

                for (int i = temp.Length - 1; i > 0; i--)
                {
                    string assemb = "";
                    for (int j = 0; j < i; j++)
                    {
                        if (assemb != "")
                            assemb += " ";
                        assemb += temp[j];
                    }

                    if (G.MeasureString(assemb, T.BlockFont).Width < (this.Width - curpos.X))
                    {
                        Ret.Add(new ChatTextBlock(T.BlockFont, assemb, T.BlockColor));
                        Ret.AddRange(this.WordWrapOnWhiteSpace(new ChatTextBlock(T.BlockFont, T.Text.Substring(assemb.Length), T.BlockColor), new PointF(0, curpos.Y + G.MeasureString(assemb, T.BlockFont).Height + 10), G));
                        return Ret.ToArray();
                    }
                }

                return null;
            }
            else
            {
                return new ChatTextBlock[] { T };
            }
        }

        public void AddLine(ChatTextLine TL)
        {
            this.Lines.Add(TL);
            this.Invalidate();
        }

        private void ChatOutputControl_Resize(object sender, EventArgs e)
        {
            this.Invalidate();
        }

        #region overridden properties (For Hiding)
        [Browsable(false)]
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                base.Text = value;
            }
        }
        [Browsable(false)]
        public override bool AutoScroll
        {
            get
            {
                return true;
            }
            set
            {
                base.AutoScroll = value;
            }
        }
        #endregion
    }
}
